// ----------------------- 1. 类装饰器 -------------------------
/**
 * 1. 定义装饰器
 * @param target 需要传入的是一个构造函数
 * 构造函数的写法： Function | new (...args: any[])=> any;
 */
function classDecorator(target: new (...args: any[]) => any) {
  console.log("class Decoration"); // class Decoration
  console.log(target); // class A
  // 对构造函数的元数据进行操作
  target.prototype.name = "你好我是修饰器 要做的操作";
}
/**
 * 装饰器应用
 */
@classDecorator
class A {}
const a = new A();
console.log((a as any).name); // 因为装饰器的作用，原型对象上已经有这个name属性了。
// 编译的时候 console.log就会自动运行。

// ----------------------- 2. 类装饰器 使用泛型约束 -------------------------
console.log("----泛型约束 装饰器的使用范围 --- ");
/**
 * 使用泛型限定 装饰器的使用条件
 */
// 定义泛型构造函数类型
type Constructor<T = any> = new (...args: any[]) => T;
type User = {
  id: number;
  name: string;
  info(): void;
};
function classDecoration2<T extends Constructor<User>>(target: T) {
  console.log("class Decoration222"); // class Decoration
  console.log(target, "222"); // class A
  // 对构造函数的元数据进行操作
  target.prototype.name = "你好我是修饰器 要做的操作22";
}

@classDecoration2
class AA {
  constructor(public id: number, public name: string) {}
  info() {}
}

// --------------装饰器工厂模式----------------
/**
 * 返回一个函数 让装饰器用函数方式调用
 */
console.log("--------------装饰器工厂模式----------------");
type ConstructorFactory<T = any> = new (...args: any[]) => T;
function classDecoratorFactory<T extends ConstructorFactory>(str: string) {
  console.log("factory mode--default console:", str);
  return function (target: T) {
    console.log("factory mode classDecorator");
    console.log("factory mode ", target);
    console.log("factory mode str", str);
    target.prototype.sex = "男";
  };
}

@classDecoratorFactory("hello factory mode")
class AAA {}
const aaa = new AAA();
console.log((aaa as any).sex);
/**
 * 直接返回一个类
 * 可以对原有的类进行 属性覆写和新增
 */
function ClassDecoratorFactoryReturnClass<T extends ConstructorFactory>(
  target: T
) {
  return class extends target {
    newProperty = "new Property";
    hello = "world";
    name = "override name rose";
    info() {
      console.log("info function");
    }
    show() {
      console.log("override show function");
    }
  };
}
@ClassDecoratorFactoryReturnClass
class AAAA {
  name: string = "jack";
  show() {
    console.log("show function");
  }
}
const aaaa = new AAAA();
console.log(aaaa.name); // name属性被override了
console.log((aaaa as any).newProperty); //
console.log((aaaa as any).info); //
console.log(aaaa.show); //

// ----------------- 多装饰器 ------------------

type Constructor_multi<T = any> = new (...args: any[]) => T;
function classDecorator11<T extends Constructor_multi>(str: string) {
  console.log("classDecorator11函数参数 ", str);
  return function (target: T) {
    console.log("classDecortor11类装饰器", str);
  };
}
function classDecorator22<T extends Constructor_multi>(str: string) {
  console.log("classDecorator22函数参数", str);
  return function (target: T) {
    console.log("classDecorator22类装饰器", str);
  };
}
@classDecorator11("1")
@classDecorator22("2")
class AAAAA {}
/**
 * 打印顺序是：
 * classDecorator11函数参数  1
 * classDecorator22函数参数 2
 * classDecorator22类装饰器 2
 * classDecortor11类装饰器 1
 */
